﻿using System;

namespace Black.SurfaceToolkit.Converters
{
    /// <summary>
    /// Applique la transformation cubique spécifiée.
    /// </summary>
    public class CubicFunctionConverter : FunctionMappingConverter
    {
        #region Accesseurs

        /// <summary>
        /// Obtient ou définit le coefficient de X^2.
        /// </summary>
        public double A
        {
            get
            {
                return (this.m_dA);
            }
            set
            {
                if (this.m_dA != value)
                {
                    this.m_dA = value;
                    this.OnControlPointsChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit le coefficient de X.
        /// </summary>
        public double B
        {
            get
            {
                return (this.m_dB);
            }
            set
            {
                if (this.m_dB != value)
                {
                    this.m_dB = value;
                    this.OnControlPointsChanged();
                }
            }
        }

        /// <summary>
        /// Obtient ou définit le coefficient constant.
        /// </summary>
        public double C
        {
            get
            {
                return (this.m_dC);
            }
            set
            {
                if (this.m_dC != value)
                {
                    this.m_dC = value;
                    this.OnControlPointsChanged();
                }
            }
        }

        #endregion

        #region Variables d'instance

        private double m_dA;
        private double m_dB;
        private double m_dC;

        #endregion

        #region Constructeurs

        /// <summary>
        /// Initalise une nouvelle instance de <see cref="T:Black.SurfaceToolkit.Converters.CubicFunctionConverter" />.
        /// </summary>
        public CubicFunctionConverter()
            : base()
        {
        }

        #endregion

        #region Fonctions publiques

        /// <summary>
        /// Obtient l'image de l'abscisse spécifiée.
        /// </summary>
        /// <param name="p_dX">Abscisse du point.</param>
        /// <returns>Image de <paramref name="p_dX" />.</returns>
        /// <exception cref="T:System.InvalidOperationException">L'obtention de l'image n'est pas possible.</exception>
        public override double GetImage(double p_dX)
        {
            return (this.m_dA * p_dX * p_dX + this.m_dB * p_dX + this.m_dC);
        }

        /// <summary>
        /// Obtient l'abscisse de l'image spécifiée.
        /// </summary>
        /// <param name="p_dY">Image du point.</param>
        /// <returns>Abscisse de <paramref name="p_dY" />.</returns>
        /// <exception cref="T:System.InvalidOperationException">L'obtention de l'abscisse n'est pas possible.</exception>
        public override double GetAbscissa(double p_dY)
        {
            double dDeltaRoot = Math.Sqrt(this.m_dB * this.m_dB - 4 * this.m_dA * this.m_dC);
            return ((-this.m_dB + dDeltaRoot) / (2 * this.m_dA));
        }

        #endregion
    }
}
